package com.up.interview.redis;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.cache.Cache;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

/**
 * @author: liuchengjun
 * @title: RedisHashCacheManager
 * @projectName: 海联技术中台V2.0
 * @depart 软件事业部
 * @description:
 * @date: 2025/10/20/周一 11:28 (星期一)
 * @since V2.0
 */
@Component
public class RedisHashCacheManager implements CommandLineRunner {
    private static final Logger logger = LoggerFactory.getLogger(RedisHashCacheManager.class);

    /** 本地缓存实例集合 - Key: wfContext:id, Value: Caffeine Cache     redis缓存: Key: dev:wfContext:id      */
    private final Map<String, ConcurrentHashMap<String, CacheValue>> localCaches = new ConcurrentHashMap<>();
    @Autowired
    private RedisCacheService redisCacheService;
    /**
     * 应用启动时执行 - 从Redis恢复本地缓存
     */
    @Override
    public void run(String... args) {
        recoverLocalCacheFromRedis();
    }

    /**
     * 从Redis恢复本地缓存
     */
    private void recoverLocalCacheFromRedis() {
        try {
            // 获取所有业务名称（Hash Key）
            Set<String> businessNames = redisCacheService.getRedisTemplate().keys("*");

            if (businessNames == null || businessNames.isEmpty()) {
                return;
            }

            int totalRecovered = 0;
            for (String businessName : businessNames) {
                try {
                    // 获取该业务的所有缓存数据
                    Map<Object, Object> entries = redisCacheService.getRedisTemplate().opsForHash().entries(businessName);

                    if (entries.isEmpty()) {
                        continue;
                    }

                    ConcurrentHashMap<String, CacheValue> caches = new ConcurrentHashMap<>();
                    // 恢复数据到本地缓存
                    for (Map.Entry<Object, Object> entry : entries.entrySet()) {
                        String field = (String) entry.getKey();
                        CacheValue value = new CacheValue(entry.getValue()) ;
                        caches.put(field, value);
                    }
                    localCaches.put(getLocalKeyForRemote(businessName),  caches);


                } catch (Exception e) {
                    logger.error("Failed to recover cache for business: {}", businessName, e);
                }
            }

            logger.info("Total recovered cache entries: {}", totalRecovered);

        } catch (Exception e) {
            logger.error("Failed to recover local cache from Redis", e);
        }
    }

    /**
     * 使用正则表达式截取
     */
    public static String getLocalKeyForRemote(String str) {
        if (str == null || str.isEmpty()) {
            return "";
        }

        return str.replaceFirst("^[^:]+:", "");
    }
    public String getLocalKey(String id) {
        return "wfContext:"+id;
    }
    public String getRemoteKey(String id) {
        //dev根据实际环境获取
        return "dev:wfContext:"+id;
    }
    /**
     * 存储缓存
     */
    public void put(Object id, String attributeName, Object attributeValue) {
        try {
            String localKey = getLocalKey((String) id);
            String remoteKey = getRemoteKey((String) id);
            //远程直接覆盖
            redisCacheService.hset(remoteKey,attributeName,attributeValue);
            Map<String, CacheValue> stringCacheValueMap = localCaches.get(localKey);
            //不存在插入
            if(stringCacheValueMap == null) {
                ConcurrentHashMap<String, CacheValue> map = new ConcurrentHashMap<>();
                map.put(attributeName,new CacheValue(attributeValue));
                localCaches.put(localKey, map);
            }
            //存在更新
            stringCacheValueMap.remove(attributeName);
            stringCacheValueMap.put(attributeName,new CacheValue(attributeValue));
        } catch (Exception e) {
            throw new RuntimeException("Cache put failed", e);
        }
    }


    /**
     * 存储缓存
     */
    public Object get(Object id, String attributeName) {
        try {
            String localKey = getLocalKey((String) id);
            String remoteKey = getRemoteKey((String) id);
            Map<String, CacheValue> stringCacheValueMap = localCaches.get(localKey);
            //不存在插入
            if(stringCacheValueMap == null) {
                return redisCacheService.hget(remoteKey,attributeName);
            }else {
                CacheValue cacheValue = stringCacheValueMap.get(attributeName);
                return cacheValue.getData();
            }
        } catch (Exception e) {
            throw new RuntimeException("Cache put failed", e);
        }
    }

    /**
     * 删除缓存
     */
    public void del(Object id, String attributeName) {
        try {
            String localKey = getLocalKey((String) id);
            String remoteKey = getRemoteKey((String) id);
            Map<String, CacheValue> stringCacheValueMap = localCaches.get(localKey);
            //不存在插入
            if(stringCacheValueMap == null) {
                redisCacheService.hdel(remoteKey,attributeName);
            }else {
                stringCacheValueMap.remove(attributeName);
            }
        } catch (Exception e) {
            throw new RuntimeException("Cache put failed", e);
        }
    }



}
